﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using HtmlAgilityPack;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;

namespace WowheadScraper
{

    class PageScraper
    {
        private string htmlString = string.Empty;

        public PageScraper(string wowHeadUrl)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(wowHeadUrl);
            request.Method = "GET";
            using (var stream = request.GetResponse().GetResponseStream())
            {
                using (var reader = new StreamReader(stream, Encoding.UTF8))
                {
                    htmlString = reader.ReadToEnd();
                }
            }            
        }

        public List<WowheadItem> ParseWowheadPageForResults()
        {
            int topBlockStart = htmlString.IndexOf("new Listview({template: 'item'");
            topBlockStart = htmlString.IndexOf("data: [")+7;
            int topBlockFinish = htmlString.IndexOf("]});\n//]]></", topBlockStart);

            StringBuilder sb = new StringBuilder();
            for (int c = topBlockStart; c < topBlockFinish; c++)
            {
                sb.Append(htmlString[c]);
            }
            string topBlock = sb.ToString();
            sb.Clear();

            string[] allItemValueStrings = topBlock.Split(',');
            int stringCounter = 0;

            string[] strPair = null;
            string valueName = string.Empty;
            WowheadItem whi;
            List<WowheadItem> items = new List<WowheadItem>();
            while ( stringCounter < allItemValueStrings.Length-1)
            {
                strPair = allItemValueStrings[stringCounter].Split(':');
                valueName = parseItemValueName(strPair[0]);               

                if (valueName == "classs")
                {
                    whi = new WowheadItem();
                    stringCounter++;
                    strPair = allItemValueStrings[stringCounter].Split(':');
                    valueName = parseItemValueName(strPair[0]); 
                    while ((valueName != "classs")&&(stringCounter<allItemValueStrings.Length-1))
                    {
                        
                        stringCounter++;

                        strPair = allItemValueStrings[stringCounter].Split(':');
                        valueName = parseItemValueName(strPair[0]);
                        string value = parseItemValueName(strPair[1]);
                        switch (valueName)
                        {
                            case "id":
                                whi.ID = int.Parse(value);
                                break;
                            case "name":
                                whi.Name = parseItemValueName(value);
                                break;
                            case "score":
                                whi.Score = Single.Parse(value);
                                break;
                            case "reqfaction":
                                whi.FactionId = int.Parse(parseItemValueName(value));
                                break;
                            case "reqrep":
                                whi.RequiredRep = int.Parse(parseItemValueName(value));
                                break;
                            default:
                                break;
                        }
                        
                    }
                    items.Add(whi);
                }
                
            }
            return items;
        }

        private string parseItemValueName(string str)
        {
            str = Regex.Replace(str, @"\s", "");
            str = str.Replace("\"", "");
            str = str.Replace("\u007D", "");
            str = str.Replace("\u007B", "");
            str = str.Replace("\\", "");
            return str;
        }

        public class WowheadItem : IComparable<WowheadItem>
        {
            public int ID { get; set; }
            public string Name { get; set; }
            public Single Score { get; set; }
            public int FactionId { get; set; }
            public int RequiredRep { get; set; }

            public int CompareTo(WowheadItem obj)
            {
                return Score.CompareTo(obj.Score);
            }
        }

    }












    class URLDesigner
    {
        private int itemType;
        private int [] subItem = null;
        private string className;
        private int classNo;
        private string specName;
        private string classSpecFilter;
        private int gemType = 4; //4 for epic gems
        private int factionNo;

        private StringBuilder url = new StringBuilder();

        public URLDesigner()
        {
            url.Append("http://www.wowhead.com/items=");
        }
            
        public string GetURL()
        {
            return url.ToString();
        }

        public void SetGemType(string gemName)
        {
            switch (gemName)
            {
                case "Epic":
                    gemType = 4;
                    break;
                case "Rare":
                    gemType = 3;
                    break;
                case "Uncommon":
                    gemType = 2;
                    break;
                default:
                    throw new Exception("Unknown gem type");
            }
            url.Append(";gm=");
            url.Append(gemType.ToString());
        }

        public void SetItemType(string itemName)
        {
            switch(itemName)
            {
                case "Weapons":
                    itemType = 2;
                    break;
                case "Armor":
                    itemType = 4;
                    break;
                case "Containers":
                    itemType = 1;
                    break;
                case "Consumables":
                    itemType = 0;
                    break;
                case "Glyphs":
                    itemType = 16;
                    break;
                case "Trade Goods":
                    itemType = 7;
                    break;
                case "Projectiles":
                    itemType = 6;
                    break;
                case "Quivers":
                    itemType = 11;
                    break;
                case "Recipes":
                    itemType = 9;
                    break;
                case "Gems":
                    itemType = 3;
                    break;
                case "Miscellaneous":
                    itemType = 15;
                    break;
                case "Currency":
                    itemType = 10;
                    break;
                case "Quest":
                    itemType = 12;
                    break;
                case "Keys":
                    itemType = 13;
                    break;
                default:
                    throw new Exception("Item type not recognised");
            }
            url.Append(itemType.ToString());            
        }

        public void SetItemSubtype(string subtype)
        {
            switch(subtype)
            {
                case "Daggers":
                    subItem = new int[1]{15};
                    break;
                case "Fist Weapons":
                    subItem = new int[1]{13};
                    break;
                case "One-Handed Axes":
                    subItem = new int[1]{0};
                    break;
                case "One-Handed Maces":
                    subItem = new int[1]{4};
                    break;
                case "One-Handed Swords":
                    subItem = new int[1]{7};
                    break;
                case "Polearms":
                    subItem = new int[1]{6};
                    break;
                case "Staves":
                    subItem = new int[1]{10};
                    break;
                case "Two-Handed Axes":
                    subItem = new int[1]{1};
                    break;
                case "Two-Handed Maces":
                    subItem = new int[1]{5};
                    break;
                case "Two-Handed Swords":
                    subItem = new int[1]{8};
                    break;
                case "Bows":
                    subItem = new int[1]{2};
                    break;
                case "Crossbows":
                    subItem = new int[1]{18};
                    break;
                case "Guns":
                    subItem = new int[1]{3};
                    break;
                case "Thrown":
                    subItem = new int[1]{16};
                    break;
                case "Wands":
                    subItem = new int[1]{19};
                    break;
                case "Fishing Poles":
                    subItem = new int[1]{20};
                    break;
                case "Miscellaneous":
                    subItem = new int[1]{14};
                    break;
                case "One-Handed":
                    subItem = new int[5] { 15, 13, 0, 4, 7 };
                    break;
                case "Two-Handed":
                    subItem = new int[5] { 6, 10, 1, 5, 8 };
                    break;
                case "Ranged":
                    subItem = new int[5] { 2, 18, 3, 16, 19 };
                    break;
                case "Other":
                    subItem = new int[2] { 20, 14 };
                    break;
                default:
                    throw new Exception("Item sub type not recognised - " +subtype);
            }
            url.Append("?filter=ty=");
            for (int i=0;i<subItem.Length;i++)
            {
                url.Append(subItem[i].ToString());
                if ((subItem.Length > 1)&&(i<subItem.Length-1))
                    url.Append("%3A");
            }
            
        }

        public void SetPresetClass(string _className, string _specName)
        {
            specName = _specName;
            className = _className;
            switch (className)
            {
                case "Druid":
                    classNo = 11;
                    switch (specName)
                    {
                        case "Balance (DPS)":
                            classSpecFilter = ";wt=23:123:24:103:119:170:96;wtv=100:100:90:90:90:80:70";
                            break;
                        case "Feral (DPS)":
                            classSpecFilter = ";wt=32:21:20:77:170:103:117:119:96;wtv=151:100:78:37:35:32:29:28:28";
                            break;
                        case "Feral (Tank)":
                            classSpecFilter = ";wt=22:41:21:45:109:170:96:20:117:115:97:77:119:103;wtv=100:75:48:41:21:16:13:10:10:7:5:5:5:1";
                            break;
                        case "Restoration (Healing)":
                            classSpecFilter = ";wt=32:21:20:77:170:103:117:119:96;wtv=151:100:78:37:35:32:29:28:28";
                            break;
                    }
                    break;
                    
                default:
                    throw new Exception("Class/spec not implemented");
            }
            //url.Append("filter=ub="); //commented to remove "druid only" during testing
            //url.Append(classNo.ToString());
            
            url.Append("filter=sl=17");
            url.Append(classSpecFilter);
        }

        public void SetReputationType(string _factionName)
        {
            switch (_factionName)
            {
                case "Any":
                    factionNo = -2323;break;
                case "Baradin's Wardens":
                    factionNo = 1177;break;
                case "Guardians of Hyjal":
                    factionNo = 1158; break;
                case "Hellscream's Reach":
                    factionNo = 1178; break;
                case "Ramkahen":
                    factionNo = 1173; break;
                case "The Earthen Ring":
                    factionNo = 1135; break;
                case "Therazane":
                    factionNo = 1171; break;
                case "Wildhammer Clan":
                    factionNo = 1174; break;
                default:
                    throw new Exception("Faction not found");
            }

            url.Append(";cr=17"); // 17 for the "Requires Reputation With..." filter
            url.Append(";crs=");
            url.Append(factionNo.ToString());
            url.Append(";crv=0"); // this is used, but always 0 for "Requires Reputation With..." filter
        }
        
    }

    
}
